package com.rslai.base.tool.servertest.preprocessor;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Element;

public class XMLProcessor {
    public static final String splitter = "@@$$@@";
    public static final String DEFAULT = "default";
    public static final String TR = "tr";
    public static final String PARAM = "param";

    public void processKeyValueXML(Element instruction, StringBuilder sb) {
        Set titleset = getTitle(instruction);
        if (CollectionUtils.isEmpty(titleset)) {
            return;
        }
        sb.append("@@$$@@");
        sb.append(StringUtils.join(titleset, "@@$$@@"));
        sb.append("@@$$@@");
        sb.append("\n");

        Iterator iterator = instruction.elementIterator();
        Map componentMap = new HashMap();
        while (iterator.hasNext()) {
            Element row = (Element) iterator.next();
            if ("default".equals(row.getName())) {
                componentMap = processRow(row);
            } else if ("tr".equals(row.getName())) {
                Map trMap = processRow(row);
                Map tempMap = copyMap(componentMap);
                tempMap.putAll(trMap);
                generateBuilder(tempMap, titleset, sb);
            }
        }
    }

    private void processRow(Element trRow, Set titleSet) {
        Iterator lineIterator = trRow.elementIterator();
        do {
            if (!lineIterator.hasNext())
                break;
            Element row = (Element) lineIterator.next();
            if (!"param".equals(row.getName()))
                return;
            if (StringUtils.isBlank(row.getText())) {
                Iterator it = row.attributeIterator();
                while (it.hasNext()) {
                    Attribute attribute = (Attribute) it.next();
                    titleSet.add(attribute.getName());
                }
            } else {
                Iterator it = row.attributeIterator();
                if (it.hasNext()) {
                    Attribute attribute = (Attribute) it.next();
                    titleSet.add(attribute.getValue());
                }
            }
        } while (true);
    }

    private Map<String, String> processRow(Element trRow) {
        Iterator lineIterator = trRow.elementIterator();
        Map rowMap = new HashMap();
        do {
            if (!lineIterator.hasNext())
                break;
            Element row = (Element) lineIterator.next();
            if (!"param".equals(row.getName()))
                return null;
            if (StringUtils.isBlank(row.getText())) {
                Iterator it = row.attributeIterator();
                while (it.hasNext()) {
                    Attribute attribute = (Attribute) it.next();
                    rowMap.put(attribute.getName(), attribute.getValue());
                }
            } else {
                Iterator it = row.attributeIterator();
                if (it.hasNext()) {
                    Attribute attribute = (Attribute) it.next();
                    rowMap.put(attribute.getValue(), row.getTextTrim());
                }
            }
        } while (true);
        return rowMap;
    }

    private Set<String> getTitle(Element instruction) {
        Set titleSet = new HashSet();
        Iterator iterator = instruction.elementIterator();
        while (iterator.hasNext()) {
            Element row = (Element) iterator.next();
            if ("default".equals(row.getName())) {
                processRow(row, titleSet);
            }
            if ("tr".equals(row.getName())) {
                processRow(row, titleSet);
            }
        }

        return titleSet;
    }

    private void generateBuilder(Map<String, String> map, Set<String> titleset, StringBuilder sb) {
        Iterator iterator = titleset.iterator();
        sb.append("@@$$@@");
        while (iterator.hasNext()) {
            String title = (String) iterator.next();
            if (map.containsKey(title))
                sb.append((String) map.get(title));
            else {
                sb.append("${").append(title).append("}");
            }
            sb.append("@@$$@@");
        }
        sb.append("\n");
    }

    private Map<String, String> copyMap(Map<String, String> srcMap) {
        Map dstMap = new HashMap();
        Iterator iterator = srcMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();

            dstMap.put(entry.getKey(), entry.getValue());
        }
        return dstMap;
    }
}
